/**
 * @file client.cpp
 * @brief Client class methods implementation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 3 of the License.
 *
 * @author VestniK (Sergey N.Vidyuk) sir.vestnik@gmail.com
 * @date 25 Jan 2009
 */
#include "client.h"

#include <QtCore/QtGlobal>
#include <QtCore/QUuid>
#include <QtCore/QSettings>
#include <QtNetwork/QTcpSocket>

#include <QRemoteSignal>

#include "sessionclient.h"
#include "gameclient.h"
#include "playerclient.h"
#include "defaults.h"

using namespace mjn;

Client::Client(QObject *parent): QObject(parent) {
    mSocket = 0;
    mManager = new qrs::ServicesManager(this);
    mSession = new qrs::SessionClient(mManager);
    connect( mSession,SIGNAL(sessionStarted(QUuid)),
             this,SLOT(onSessionStarted(QUuid)) );
    connect( mSession,SIGNAL(noSlots()),
             this,SLOT(onNoSlots()) );
    mGame = new qrs::GameClient(this);
    mPlayer = new qrs::PlayerClient(this);
}

Client::~Client() {
}

void Client::connectToHost(const QString& host, quint16 port) {
    if (port == 0) {
        QSettings settings;
        port = settings.value("port",DEFAULT_PORT).value<quint16>();
    }
    if ( mSocket != 0 ) {
        if ( mSocket->state() == QAbstractSocket::ConnectedState ) {
            /// @todo provide meaningfull reaction on attempt to connet while
            /// connection already established
            return;
        }
        delete mSocket;
    }
    mSocket = new QTcpSocket(this);
    // initialization
    connect( mSocket,SIGNAL(connected()),
             this,SLOT(onSocketConnected()) );
    connect( mSocket,SIGNAL(error(QAbstractSocket::SocketError)),
             this,SLOT(onSocketError(QAbstractSocket::SocketError)) );
    connect( mSocket,SIGNAL(disconnected()),
             this,SLOT(onSocketDisconnected()) );
    mSid = QUuid();
    mSocket->connectToHost(host,port);
}

void Client::onSocketConnected() {
    mManager->addDevice(mSocket);
    mSession->init();
}

/**
 * Creates clients for the game and the player services and emits signal
 * Client::connected()
 */
void Client::onSessionStarted(const QUuid &sid) {
    mSid = sid;
    mManager->registerService(mGame);
    mManager->registerService(mPlayer);
    emit connected();
    mPlayer->setName(mName);
}

void Client::onNoSlots() {
    emit connectionError(tr("No free slots on the server."));
    mSocket->disconnectFromHost();
}

void Client::onSocketError(QAbstractSocket::SocketError socket_error) {
    emit connectionError(mSocket->errorString());
    if ( mSocket->state() < QAbstractSocket::ConnectedState ) {
        emit connectionFailed();
    }
}

void Client::onSocketDisconnected() {
    if ( mSid.isNull() ) {
        emit connectionFailed();
    } else {
        emit disconnected();
    }
}
